/**
 * 视频解码器 libX264
 * RGB(红、绿、蓝):是一种颜色编码方法。RGB色彩就是常说的光学三原色，R代表Red（红色），G代表Green（绿色），B代表
 *  Blue（蓝色）。如果我们用放大镜去观察电脑显示器或电视机的屏幕，就会看到数量极多的红色、绿色、蓝色三种颜色的小点。
 *
 * YUV:是一种颜色编码方法，跟RGB是同一级别的概念，广泛应用于多媒体领域，图像中每1个像素的颜色信息，除了可以用RGB的
 *  方式表示，还可以用YUV的方式表示
 *  1.与RGB相比的优越点 如下YUV是4:2:0采样格式
 *      1.体积
 *          RGB中1个像素占用24bit(3字节)
 *          YUV中1个像素占用12bit(1.5字节)
 *      2.组成
 *          RGB由R、G、B三个分量组成
 *          YUV由Y、U、V三个分量组成，现在通常说YUV指的是YCbCr
 *              Y:表示亮度(Luminance、Luma)，占8bit(1字节)
 *              Cb、Cr:表示色度(Chrominance、Chroma)
 *                  Cb(U):蓝色色度分量，占2bit
 *                  Cr(V):红色色度分量，占2bit
 *      3.兼容性
 *          RGB 三个单独分量显示图异常
 *          YUV：Y分量对呈现出清晰的图像有很大的共享，Cb、Cr分量的内容不太容易识别。
 *          早期的黑白电视机就是只接受了Y分量，后期的彩色电视机接受了Cb、Cr之后添加了色彩
 *  2.转换
 *      1.公式1:RGB的取值范围[0,255], Y的取值范围[16,235] UV的取值范围[16,239]
 *          Y = 0.257R + 0.504G + 0.098B + 16
 *          U = -0.148R - 0.291G + 0.439B + 128
 *          V = 0.439R - 0.368G - 0.071B + 128
 *
 *          R = 1.164(Y - 16) + 2.018(U - 128)
 *          G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128)
 *          B = 1.164(Y - 16) + 1.596(V - 128)
 *      2.公式2:RGB的取值范围[0,1], Y的取值范围[0,1] UV的取值范围[-0.5,0.5]
 *          Y = 0.299R + 0.587G + 0.114B
 *          U = 0.564(B - Y) = -0.169R - 0.331G + 0.500B
 *          V = 0.713(R - Y) = 0.500R - 0.419G - 0.081B
 *
 *          R = Y + 1.403V
 *          G = Y - 0.344U - 0.714V
 *          B = Y + 1.770U
 *      3.公式3:RGB的取值范围[0,255], YUV的取值范围[0,255]
 *          Y = 0.299R + 0.587G + 0.114B
 *          U = -0.169R - 0.331G + 0.500B + 128
 *          V = 0.500R - 0.419G - 0.081B + 128
 *
 *          R = Y + 1.403(V - 128)
 *          G = Y - 0.343(U - 128) - 0.714(V - 128)
 *          B = Y + 1.770(U - 128)
 *  3.概念
 *      1.采样格式：采样格式通常采用A:B:C的形式表示，如4:4:4、4:2:2、4:2:0等，其中最常用的是4:2:0
 *          A:一块A*2个像素的概念区域，一般都是4
 *          B:第一行的色度采样数目
 *          C:第二行的色度采样数目 C的值一般么等于B、要么等于0
 *          不管是那种采样格式，Y分量都是全水平、全垂直分辨率采样的，每一个像素都有自己独立的Y分量
 *          采样格式:4:4:4
 *              第1行采集4组CbCr分量，第2行采集4组CbCr分量
 *              每1个像素都有自己独立的1组CbCr分量
 *                  Y分量与CbCr分量的水平方向比例是1:1（每1列都有1组CbCr分量）
 *                  Y分量与CbCr分量的垂直方向比例是1:1（每1行都有1组CbCr分量）
 *                  Y分量与CbCr分量的总比例是1:1
 *              1个像素占用24bit(3字节),跟RGB888的体积一样
 *          采样格式:4:2:2
 *              第1行采集2组CbCr分量，第2行采集2组CbCr分量
 *              水平方向相邻的2个像素(1行2列)公用1组CbCr分量
 *                  Y分量与CbCr分量的水平方向比例是2:1（每2列就有1组CbCr分量）
 *                  Y分量与CbCr分量的垂直方向比列是1:1（每1行都有1组CbCr分量）
 *                  Y分量与CbCr分量的总比例是2:1
 *              1个像素平均占用16bit(2字节)
 *          采样格式:4:2:0
 *              第1行采集2组CbCr分量，第2行共享第1行的CbCr分量
 *              相邻的4个像素(2行2列)公用一组CbCr分量
 *                  Y分量与CbCr分量的水平方向比例是2:1（每2列就有1组CbCr分量）
 *                  Y分量与CbCr分量的垂直方向比例是2:1（每2行就有1组CbCr分量）
 *                  Y分量与CbCr分量的总比例是4:1
 *              1个像素平均占用12bit(1.5字节)
 *      2.存储格式:决定YUV数据是如何排列和存储
 *          Planar(平面):Y、U、V分量分开单独存储，名称通道以字母p结尾
 *          Semi-Planar(半平面):Y分量单独存储，U、V分量交错存储
   *          Packed(紧凑):Y、U、V分量交错存储
 *          4:4:4 Planar        I444(yuv444p)
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              U U U U
 *                              U U U U
 *                              V V V V
 *                              V V V V
 *          4:4:4 Planar        YV24
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              V V V V
 *                              V V V V
 *                              U U U U
 *                              U U U U
 *          4:4:4 Semi-Planar   NV24
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              U V U V U V U V
 *                              U V U V U V U V
 *          4:4:4 Semi-Planar   NV42
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              V U V U V U V U
 *                              V U V U V U V U
 *          4:2:2 Planar        I422(yuv422p)
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              U U
 *                              U U
 *                              V V
 *                              V V
 *          4:2:2 Planar        YV16
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              V V
 *                              V V
 *                              U U
 *                              U U
 *          4:2:2 Semi-Planar   NV16
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              U V U V
 *                              U V U V
 *          4:2:2 Semi-Planar   NV61
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              V U V U
 *                              V U V U
 *          4:2:2 Packed        UYUV(Y422、UYNV)
 *                              U Y V Y U Y V Y
 *                              U Y V Y U Y V Y
 *          4:2:2 Packed        YUYV(YUY2、V422、YUNV)
 *                              Y U Y V Y U Y V
 *                              Y U Y V Y U Y V
 *          4:2:2 Packed        YVYU
 *                              Y V Y U Y V Y U
 *                              Y V Y U Y V Y U
 *          4:2:0 Planar        I420(yuv420p) 大多数视频解码器以I420格式输出原始图片
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              U U
 *                              V V
 *          4:2:0 Planar        YV12
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              V V
 *                              U U
 *          4:2:0 Semi-Planar   NV12
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              U V U V
 *          4:2:0 Semi-Planar   NV21
 *                              Y Y Y Y
 *                              Y Y Y Y
 *                              V U V U
 */

#include "X264Decoder.h"

const AVCodec *X264Decoder::findCodec(DecoderParam &decoderParam) {
  return avcodec_find_decoder_by_name("libx264");
}

int32_t X264Decoder::initContextParam(AVCodecContext *pCodecCtx, DecoderParam &decoderParam) {
  int32_t ret = avcodec_parameters_to_context(pCodecCtx, decoderParam.pStream->codecpar);
  if (ret < SUCCESS) {
    return ret;
  }

  return SUCCESS;
}

MediaType X264Decoder::getMediaType() {
  return MediaType_Video;
}

const char *X264Decoder::getClassName() {
  return "X264Decoder";
}

void X264Decoder::toString() {
  LOG_TEST("X264Decoder()")
}
